package com.codedancer.campus.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.client.service.ICircleService;
import com.codedancer.campus.client.service.bo.circle.CircleCreateBo;
import com.codedancer.campus.client.service.bo.circle.CirclePageSearchBo;
import com.codedancer.campus.client.service.vo.circle.CirclePageVo;
import com.codedancer.campus.client.service.vo.circle.CircleVo;
import com.codedancer.campus.common.dataresource.ExternalApiData;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.CircleStatus;
import com.codedancer.campus.mapper.CircleFollowMapper;
import com.codedancer.campus.mapper.CircleLabelMapper;
import com.codedancer.campus.mapper.CircleMapper;
import com.codedancer.campus.mapper.DynamicMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.Circle;
import com.codedancer.campus.po.CircleFollow;
import com.codedancer.campus.po.CircleLabel;
import com.codedancer.campus.po.UserSchool;
import com.codedancer.campus.qo.circle.CirclePageSearchQo;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(rollbackFor = Exception.class)
public class CircleServiceImpl implements ICircleService {

    @Autowired
    private CircleMapper circleMapper;
    @Autowired
    private UserSchoolMapper userSchoolMapper;
    @Autowired
    private CircleFollowMapper circleFollowMapper;
    @Autowired
    private CircleLabelMapper circleLabelMapper;
    @Autowired
    private DynamicMapper dynamicMapper;
    @Autowired
    private ExternalApiData externalApiData;

    /**
     * 创建圈子
     *
     * @param circleCreateBo
     */
    @Override
    public void create(CircleCreateBo circleCreateBo) {
        // 判断是否存在敏感词
        if (externalApiData.checkSensitiveWords(circleCreateBo.getDescription())) {
            throw new BusinessException("圈子描述存在敏感词，请重新填写");
        }
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", circleCreateBo.getCurrentUserUuid());
        if (CollectionUtil.isEmpty(circleCreateBo.getLabels())
            || circleCreateBo.getLabels().size() < 5) {
            throw new BusinessException("请至少填写五个标签");
        }
        // 判断该学校圈子标题是否存在
        if (circleMapper
            .existsBySchoolUuidAndName(userSchool.getSchoolUuid(), circleCreateBo.getTitle())) {
            throw new BusinessException("圈子名称已存在，请重新填写");
        }
        Circle circle = BeanUtil.copyProperties(circleCreateBo, Circle.class);
        circle.setUuid(UUIDGenerator.getUUID());
        circle.setStatus(CircleStatus.PENDING_REVIEW);
        circle.setCreateUserUuid(circleCreateBo.getCurrentUserUuid());
        circle.setCreateSchoolUuid(userSchool.getSchoolUuid());
        circleMapper.insert(circle);
        // 先判断是否存在重复标签
        long distinctCount = circleCreateBo.getLabels().stream().distinct().count();
        if (distinctCount != circleCreateBo.getLabels().size()) {
            throw new BusinessException("存在重复标签，请重新填写");
        }
        // 保存标签
        for (String label : circleCreateBo.getLabels()) {
            CircleLabel circleLabel = CircleLabel.builder()
                .uuid(UUIDGenerator.getUUID())
                .circleUuid(circle.getUuid())
                .name("#" + label).build();
            circleLabelMapper.insert(circleLabel);
        }
    }

    /**
     * 查询圈子排名前十
     *
     * @param currentUserUuid
     * @return
     */
    @Override
    public List<CircleVo>
    top10(String currentUserUuid) {
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", currentUserUuid);
        List<Circle> circles = circleMapper.top10OrderByFollowCount(userSchool.getSchoolUuid());
        List<CircleVo> circleVos;
        circleVos = circles.stream().map(circle -> {
            CircleVo circleVo = BeanUtil.copyProperties(circle, CircleVo.class);
            // 判断当前用户是否关注
            circleVo
                .setIsFollow(circleFollowMapper.isFollow(circle.getUuid(), currentUserUuid));
            return circleVo;
        }).collect(Collectors.toList());
        return circleVos;
    }

    /**
     * 关注圈子
     *
     * @param uuid
     */
    @Override
    public void follow(String uuid, String currentUserUuid) {
        Circle circle = circleMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        // 判断是否已关注
        if (circleFollowMapper.isFollow(uuid, currentUserUuid)) {
            throw new BusinessException("不能重复关注");
        }
        CircleFollow circleFollow = CircleFollow.builder()
            .circleUuid(uuid)
            .followUserUuid(currentUserUuid)
            .build();
        circleFollowMapper.insert(circleFollow);
        // 圈子关注量加1
        circle.setFollowCount(circle.getFollowCount() + 1);
        circleMapper.updateById(circle);
    }

    /**
     * 取消关注
     *
     * @param uuid
     * @param currentLoginUuid
     */
    @Override
    public void cancelFollow(String uuid, String currentLoginUuid) {
        Circle circle = circleMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        circleFollowMapper.cancelFollow(uuid, currentLoginUuid);
        // 关注数量减1
        circle.setFollowCount(circle.getFollowCount() - 1);
        circleMapper.updateById(circle);
    }

    /**
     * 分页查询圈子
     *
     * @param circlePageSearchBo
     * @return
     */
    @Override
    public IPage<CirclePageVo> page(CirclePageSearchBo circlePageSearchBo) {
        CirclePageSearchQo circlePageSearchQo = BeanUtil
            .copyProperties(circlePageSearchBo, CirclePageSearchQo.class);
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", circlePageSearchBo.getCurrentUserUuid());
        circlePageSearchQo.setSchoolUuid(userSchool.getSchoolUuid());
        IPage<Circle> circleIPage = circleMapper.pageToClient(
            new Page<Circle>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
            circlePageSearchQo);
        List<CirclePageVo> circlePageVos;
        IPage<CirclePageVo> circlePageVoIPage = new Page<>();
        circlePageVos = circleIPage.getRecords().stream()
            .map(circle -> {
                return BeanUtil.copyProperties(circle, CirclePageVo.class);
            }).collect(Collectors.toList());
        circlePageVoIPage.setRecords(circlePageVos);
        circlePageVoIPage.setTotal(circleIPage.getTotal());
        return circlePageVoIPage;
    }

    /**
     * 圈子详情
     *
     * @param uuid
     * @return
     */
    @Override
    public CircleVo detail(String uuid, String currentUserUuid) {
        Circle circle = circleMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        CircleVo circleVo = BeanUtil.copyProperties(circle, CircleVo.class);
        // 获取关注数
        int followCount = circleFollowMapper.countByColumn("circle_uuid", uuid);
        circleVo.setFollowCount(followCount);
        // 判断该用户是否关注
        circleVo.setIsFollow(circleFollowMapper.isFollow(uuid, currentUserUuid));
        // 根据圈子查询动态数量
        int dynamicCount = dynamicMapper.countByCircleUuid(uuid);
        circleVo.setDynamicCount(dynamicCount);
        // 获取圈子关联标签
        List<CircleLabel> circleLabels = circleLabelMapper
            .selectListByColumn("circle_uuid", circle.getUuid());
        circleVo.setCircleLabels(
            circleLabels.stream().map(CircleLabel::getName).collect(Collectors.toList()));
        return circleVo;
    }

    /**
     * 获取某个学校全部圈子
     *
     * @return
     */
    @Override
    public List<CircleVo> listBySchoolUuid(String currentUserUuid) {
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", currentUserUuid);
        List<Circle> circles = circleMapper.listBySchoolUuid(userSchool.getSchoolUuid());
        return circles.stream().map(circle -> BeanUtil.copyProperties(circle, CircleVo.class))
            .collect(Collectors.toList());
    }

    /**
     * 分页查询用户关注或创建的圈子
     *
     * @param circlePageSearchBo
     * @return
     */
    @Override
    public IPage<CirclePageVo> page2User(CirclePageSearchBo circlePageSearchBo) {
        CirclePageSearchQo circlePageSearchQo = BeanUtil
            .copyProperties(circlePageSearchBo, CirclePageSearchQo.class);
        if (ObjectUtil.isEmpty(circlePageSearchBo.getType())) {
            throw new BusinessException("查询类型不能为空");
        }
        List<CirclePageVo> circlePageVos = null;
        IPage<CirclePageVo> circlePageVoIPage = new Page<>();
        if (circlePageSearchBo.getType().equals("follow")) {
            // 查询关注的圈子
            IPage<CircleFollow> circleFollowIPage = circleFollowMapper.pageFollow(
                new Page<CircleFollow>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
                circlePageSearchQo);
            circlePageVos = circleFollowIPage.getRecords().stream().map(circleFollow -> {
                // 查询圈子
                Circle circle = circleMapper.selectById(circleFollow.getCircleUuid());
                return BeanUtil.copyProperties(circle, CirclePageVo.class);
            }).collect(Collectors.toList());
        }
        if (circlePageSearchBo.getType().equals("create")) {
            // 查询我创建的圈子
            IPage<Circle> circleIPage = circleMapper
                .pageCreate(
                    new Page<Circle>(circlePageSearchBo.getPage(), circlePageSearchBo.getSize()),
                    circlePageSearchQo);
            circlePageVos = circleIPage.getRecords().stream()
                .map(circle -> BeanUtil.copyProperties(circle, CirclePageVo.class))
                .collect(Collectors.toList());
        }
        circlePageVoIPage.setRecords(circlePageVos);
        return circlePageVoIPage;
    }

    /**
     * 启用圈子
     *
     * @param uuid
     */
    @Override
    public void enable(String uuid) {
        Circle circle = circleMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        circle.setDisabled(false);
        circleMapper.updateById(circle);
    }

    /**
     * 禁用圈子
     *
     * @param uuid
     */
    @Override
    public void disable(String uuid) {
        Circle circle = circleMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        circle.setDisabled(true);
        circleMapper.updateById(circle);
    }

    /**
     * 删除圈子
     *
     * @param uuid
     */
    @Override
    public void delete(String uuid) {
        // 删除圈子关联的数据信息
        // 删除用户关注的圈子
        circleFollowMapper.deleteByColumn("circle_uuid", uuid);
        circleMapper.deleteById(uuid);
    }

    /**
     * 修改圈子
     *
     * @param circleCreateBo
     */
    @Override
    public void update(CircleCreateBo circleCreateBo) {
        Circle circle = circleMapper.findById(circleCreateBo.getUuid())
            .orElseThrow(() -> new BusinessException("圈子不存在"));
        // 判断是否存在敏感词
        if (externalApiData.checkSensitiveWords(circleCreateBo.getDescription())) {
            throw new BusinessException("圈子描述存在敏感词，请重新填写");
        }
        if (CollectionUtil.isEmpty(circleCreateBo.getLabels())
            || circleCreateBo.getLabels().size() < 5) {
            throw new BusinessException("请至少填写五个标签");
        }
        UserSchool userSchool = userSchoolMapper
            .selectOneByColumn("user_uuid", circleCreateBo.getCurrentUserUuid());
        // 判断该学校圈子标题是否存在
        if (!circle.getTitle().equals(circleCreateBo.getTitle())) {
            if (circleMapper
                .existsBySchoolUuidAndName(userSchool.getSchoolUuid(), circleCreateBo.getTitle())) {
                throw new BusinessException("圈子名称已存在，请重新填写");
            }
        }
        // 先判断是否存在重复标签
        long distinctCount = circleCreateBo.getLabels().stream().distinct().count();
        if (distinctCount != circleCreateBo.getLabels().size()) {
            throw new BusinessException("存在重复标签，请重新填写");
        }
        BeanUtil.copyProperties(circleCreateBo, circle);
        circle.setStatus(CircleStatus.PENDING_REVIEW);
        circleMapper.updateById(circle);
        // 先删除关联的标签
        circleLabelMapper.deleteByColumn("circle_uuid", circle.getUuid());
        // 保存标签
        for (String label : circleCreateBo.getLabels()) {
            CircleLabel circleLabel = CircleLabel.builder()
                .uuid(UUIDGenerator.getUUID())
                .circleUuid(circle.getUuid())
                .name("#" + label).build();
            circleLabelMapper.insert(circleLabel);
        }
    }
}
